package blockr.function;

import blockr.model.RandomNumOBJ;
import blockr.util.Byte_KMP;
import blockr.util.Byte_SHIFT;
import blockr.util.Byte_XOR;

public class Decrypt_End_Piece {

    public static void Do_Decrypt_End_Piece(byte[][][] allBlock, RandomNumOBJ firstBlockKey, int arraySize) {
        byte[][] final_block = allBlock[MappedBiggerFileReader.getBlock_index()];
        byte[] final_piece = final_block[(MappedBiggerFileReader.getPiece_index() % (arraySize * 8)) - 1];   //n-1
        byte[] end_piece = final_block[(MappedBiggerFileReader.getPiece_index()) % (arraySize * 8)]; //n
        boolean endAllZero = true;
        for (byte indexByte : end_piece) {
            if (indexByte != 0) {
                endAllZero = false;
            }
        }
        /*end_piece全0，只有final_piece有用*/
        if (endAllZero) {
            final_piece = calculate(final_piece, firstBlockKey, (MappedBiggerFileReader.getPiece_index() % (arraySize * 8)) - 1, arraySize);
            final_piece = abandon_random_num(final_piece);
            final_block[(MappedBiggerFileReader.getPiece_index() % (arraySize * 8)) - 1] = final_piece;
            final_block[(MappedBiggerFileReader.getPiece_index()) % (arraySize * 8)] = null;
            allBlock[MappedBiggerFileReader.getBlock_index()] = final_block;
        } else {
            final_piece = calculate(final_piece, firstBlockKey, (MappedBiggerFileReader.getPiece_index() % (arraySize * 8)) - 1, arraySize);
            end_piece = calculate(end_piece, firstBlockKey, (MappedBiggerFileReader.getPiece_index() % (arraySize * 8)) - 2, arraySize);
            /*end_piece中有标识符ICCODE 与填充时的不添加新片完成填充情况对应*/
            if (Byte_KMP.find(end_piece) == 0) {
                end_piece = abandon_random_num(end_piece);
                final_block[(MappedBiggerFileReader.getPiece_index() % (arraySize * 8)) - 1] = end_piece;
                allBlock[MappedBiggerFileReader.getBlock_index()] = final_block;
            }
            /*final_piece中有标识符ICCODE 与填充时的添加新片完成填充情况对应 新片中全是随机数 直接放弃*/
            else if (Byte_KMP.find(final_piece) == 0) {
                final_piece = abandon_random_num(final_piece, end_piece, arraySize); //end_piece将要设为空
                final_block[(MappedBiggerFileReader.getPiece_index() % (arraySize * 8)) - 1] = final_piece;
                final_block[(MappedBiggerFileReader.getPiece_index()) % (arraySize * 8)] = null;
                allBlock[MappedBiggerFileReader.getBlock_index()] = final_block;
            }
        }
    }

    public static void Do_Decrypt_End_Piece_1(byte[][][] allBlock, RandomNumOBJ firstBlockKey, int arraySize) {
        byte[][] final_block = allBlock[MappedBiggerFileReader.getBlock_index()];
        byte[] final_piece;
        byte[] end_piece;
        if (MappedBiggerFileReader.isAdd()) {   //有加新片
            if (MappedBiggerFileReader.getPiece_index() % (arraySize * 8) == 0) {  //新添加的片与原来的最后一片不在同一块上
                byte[][] end_block = allBlock[MappedBiggerFileReader.getBlock_index()];
                final_block = allBlock[MappedBiggerFileReader.getBlock_index() - 1];
                final_piece = final_block[arraySize * 8 - 1];    //n-1
                end_piece = end_block[0];   //n
                final_piece = calculate(final_piece, firstBlockKey, arraySize * 8 - 1, arraySize);
                end_piece = calculate(end_piece, firstBlockKey, arraySize * 8, arraySize);
                final_piece = abandon_random_num(final_piece, end_piece, arraySize);
                final_block[arraySize * 8 - 1] = final_piece;
                allBlock[MappedBiggerFileReader.getBlock_index() - 1] = final_block;
                end_block[0] = null;    //end_piece将要设为空
                allBlock[MappedBiggerFileReader.getBlock_index() - 1] = final_block;
                allBlock[MappedBiggerFileReader.getBlock_index()] = end_block;
            } else {    //新添加的片与原来的最后一片在同一块上
                final_piece = final_block[(MappedBiggerFileReader.getPiece_index() % (arraySize * 8)) - 1];   //n-1
                end_piece = final_block[(MappedBiggerFileReader.getPiece_index()) % (arraySize * 8)]; //n
                final_piece = calculate(final_piece, firstBlockKey, (MappedBiggerFileReader.getPiece_index() % (arraySize * 8)) - 1, arraySize);
                end_piece = calculate(end_piece, firstBlockKey, (MappedBiggerFileReader.getPiece_index()) % (arraySize * 8), arraySize);
                final_piece = abandon_random_num(final_piece, end_piece, arraySize); //end_piece将要设为空
                final_block[(MappedBiggerFileReader.getPiece_index() % (arraySize * 8)) - 1] = final_piece;
                final_block[(MappedBiggerFileReader.getPiece_index()) % (arraySize * 8)] = null;
                allBlock[MappedBiggerFileReader.getBlock_index()] = final_block;
            }
        } else {    //未加新片
//            final_piece = final_block[(MappedBiggerFileReader.getPiece_index() % 1024) - 2];   //n-1
            end_piece = final_block[(MappedBiggerFileReader.getPiece_index() % (arraySize * 8)) - 1];   //n
            end_piece = calculate(end_piece, firstBlockKey, (MappedBiggerFileReader.getPiece_index() % (arraySize * 8)) - 1, arraySize);
            end_piece = abandon_random_num(end_piece);
            final_block[(MappedBiggerFileReader.getPiece_index() % (arraySize * 8)) - 1] = end_piece;
            allBlock[MappedBiggerFileReader.getBlock_index()] = final_block;
        }
        //测试最后片
        /*try {
            if (MappedBiggerFileReader.isAdd()) {
                byte[] union = new byte[end_piece.length];
                System.arraycopy(end_piece, 0, union, 0, end_piece.length);
                String test_doc=new String(union, "UTF-8");
                System.out.println(test_doc);
            }
        } catch (UnsupportedEncodingException | ArrayIndexOutOfBoundsException e) {
            e.printStackTrace();
        }*/
    }

    private static byte[] abandon_random_num(byte[] end_piece) {
        int G_begin = Byte_KMP.find(end_piece);
        byte[] new_end_piece = new byte[G_begin];
        System.arraycopy(end_piece, 0, new_end_piece, 0, G_begin);
        return new_end_piece;
    }

    private static byte[] abandon_random_num(byte[] final_piece, byte[] end_piece, int arraySize) {
        byte[] union = new byte[arraySize * 2];
        System.arraycopy(final_piece, 0, union, 0, arraySize);
        System.arraycopy(end_piece, 0, union, arraySize, arraySize);
        int G_begin = Byte_KMP.find(union);
        if (G_begin == arraySize || G_begin == 0) {
            return final_piece;
        }
        System.arraycopy(union, 0, union, 0, G_begin);
        return union;
    }

    private static byte[] calculate(byte[] piece, RandomNumOBJ firstBlockKey, int n, int arraySize) {
/*
        计算优先级错误！
        final_piece = Byte_XOR.XOR(final_piece, All_Random_Num[0].getR1());  //Cn-1^R1
        final_piece = Byte_SHIFT.leftShift(final_piece, n_1);    //Cn-1^R1<<(n-1)
        final_piece = Byte_XOR.XOR(final_piece, All_Random_Num[0].getR2());    //Cn-1^R1<<(n-1)^R2
        final_piece = Byte_SHIFT.rightShift(final_piece, n_1); //Cn-1^R1<<(n-1)^R2>>(n-1)
        end_piece = Byte_XOR.XOR(end_piece, All_Random_Num[0].getR1());    //Cn^R1
        end_piece = Byte_SHIFT.leftShift(end_piece, n);    //Cn^R1<<n
        end_piece = Byte_XOR.XOR(end_piece, All_Random_Num[0].getR2()); //Cn^R1<<(n)^R2
        end_piece = Byte_SHIFT.rightShift(end_piece, n);        //Cn^R1<<(n)^R2>>(n)*/
        byte[] R1 = firstBlockKey.getR1();
        R1 = Byte_SHIFT.leftShift(R1, n, arraySize);    //R1<<(n-1)
        byte[] R2 = firstBlockKey.getR2();
        R2 = Byte_SHIFT.rightShift(R2, n, arraySize);   //R2>>(n-1)
        piece = Byte_XOR.XOR(piece, R1);   //Cn-1^(R1<<(n-1))
        piece = Byte_XOR.XOR(piece, R2);   //Cn-1^(R1<<(n-1))^(R2>>(n-1))
        return piece;
    }
}
